package com.beyond.pm.ui.setting.system.style

import androidx.compose.animation.core.Spring
import androidx.compose.animation.core.spring
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.scaleIn
import androidx.compose.animation.scaleOut
import androidx.compose.foundation.background
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.selection.selectable
import androidx.compose.foundation.selection.selectableGroup
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Check
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.Checkbox
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.RadioButton
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Slider
import androidx.compose.material3.SliderDefaults
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.rememberModalBottomSheetState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import com.beyond.common.dp.theme.CustomPrimaryColorPreference
import com.beyond.common.dp.theme.DarkModePreference
import com.beyond.common.dp.theme.SystemPrimaryColorPreference
import com.beyond.common.dp.theme.ThemeNamePreference
import com.beyond.common.ext.checkColorHex
import com.beyond.common.ext.toColorOrNull
import com.beyond.common.local.LocalCustomPrimaryColor
import com.beyond.common.local.LocalDarkMode
import com.beyond.common.local.LocalSystemPrimaryModel
import com.beyond.common.local.LocalThemeName
import com.beyond.pm.R
import com.beyond.pm.bean.RouteScreenParameter
import com.beyond.pm.component.MyTopBar
import com.beyond.pm.component.MyTopBarStyle
import com.beyond.theme.extractAllTonalPalettes
import com.kyant.monet.PaletteStyle
import com.kyant.monet.TonalPalettes
import com.kyant.monet.TonalPalettes.Companion.toTonalPalettes
import com.kyant.monet.toSrgb

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun AppStyleScreen() {
    var openDarkBottomSheet by rememberSaveable { mutableStateOf(false) }
    Scaffold(
        topBar = {
            MyTopBar(
                style = MyTopBarStyle.CenterAligned,
                title = {
                    Row(
                        modifier = Modifier.fillMaxWidth(),
                        horizontalArrangement = Arrangement.Center,
                        verticalAlignment = Alignment.CenterVertically
                    ) {
                        Icon(
                            imageVector = RouteScreenParameter.Style.bean.icon,
                            contentDescription = null,
                        )
                        Spacer(modifier = Modifier.width(10.dp))
                        Text(text = stringResource(id = RouteScreenParameter.Style.bean.labelId))
                    }
                },
            )
        },
    ) {
        ConfigContent(it) {
            openDarkBottomSheet = true
        }
        if (openDarkBottomSheet) {
            DarkModeSheet {
                openDarkBottomSheet = false
            }
        }
    }
}

@Composable
private fun ConfigContent(paddingValues: PaddingValues, onClick: () -> Unit) {
    LazyColumn(
        modifier = Modifier
            .padding(
                PaddingValues(
                    start = 16.dp,
                    top = paddingValues.calculateTopPadding(),
                    end = 16.dp,
                    bottom = 0.dp
                )
            )
            .fillMaxSize(),
        verticalArrangement = Arrangement.spacedBy(10.dp),
    ) {
        item {
            WallpaperPalettes()
        }
        item {
            UseSystemColor()
        }
        item {
            TextButton(onClick = onClick) {
                Text(text = "夜间模式")
            }
        }
    }

}

@Composable
private fun WallpaperPalettes() {
    val wallpaperPalettes: Map<String, TonalPalettes> = extractAllTonalPalettes()
    val customPrimaryColor = LocalCustomPrimaryColor.current
    val context = LocalContext.current
    val scope = rememberCoroutineScope()
    val themeName = LocalThemeName.current
    val tonalPalettes = (customPrimaryColor.toColorOrNull() ?: Color.Transparent).toTonalPalettes(
        style = PaletteStyle.Content
    )
    var addDialogVisible by rememberSaveable { mutableStateOf(false) }
    var customColorValue by rememberSaveable { mutableStateOf(customPrimaryColor) }
    wallpaperPalettes.forEach { (t, u) ->
        val isCustom = t == ThemeNamePreference.CUSTOM_THEME_NAME
        val palette = if (isCustom) tonalPalettes else u
        Spacer(modifier = Modifier.height(10.dp))
        CheckColorPalette(t, onClick = {
            if (isCustom) {
                customColorValue = customPrimaryColor
                addDialogVisible = true
            } else {
                ThemeNamePreference.put(context, scope, t)
            }
        }, palette, t == themeName)
    }

    CustomColorDialog(visible = addDialogVisible,
        value = customColorValue,
        onDismissRequest = {
            addDialogVisible = false
        },
        onConfirm = {
            it?.checkColorHex()?.let { color ->
                CustomPrimaryColorPreference.put(context, scope, color)
                ThemeNamePreference.put(context, scope, ThemeNamePreference.CUSTOM_THEME_NAME)
                addDialogVisible = false
            }
        })

}

@Composable
private fun CheckColorPalette(
    label: String,
    onClick: () -> Unit,
    palette: TonalPalettes,
    visible: Boolean,
) {
    Surface(
        modifier = Modifier.fillMaxSize(),
        color = palette accent1 if (isSystemInDarkTheme()) 20.0 else 80.0,
        shape = CircleShape,
        onClick = onClick
    ) {
        Row(
            modifier = Modifier
                .fillMaxSize()
                .padding(start = 12.dp, end = 8.dp)
        ) {
            Text(
                modifier = Modifier
                    .weight(1f)
                    .align(alignment = Alignment.CenterVertically), text = label
            )
            Surface(
                modifier = Modifier
                    .padding(2.dp)
                    .size(40.dp),
                shape = CircleShape,
                color = palette accent1 90.0,
            ) {
                Box {
                    Surface(
                        modifier = Modifier
                            .size(40.dp)
                            .offset((-20).dp, 20.dp),
                        color = palette accent3 90.0,
                    ) {}
                    Surface(
                        modifier = Modifier
                            .size(40.dp)
                            .offset(20.dp, 20.dp),
                        color = palette accent2 60.0,
                    ) {}
                    val animationSpec = spring<Float>(stiffness = Spring.StiffnessMedium)
                    androidx.compose.animation.AnimatedVisibility(
                        visible = visible,
                        enter = scaleIn(animationSpec) + fadeIn(animationSpec),
                        exit = scaleOut(animationSpec) + fadeOut(animationSpec),
                    ) {
                        Box(
                            modifier = Modifier
                                .padding(10.dp)
                                .fillMaxSize()
                                .clip(CircleShape)
                                .background(MaterialTheme.colorScheme.primary),
                            contentAlignment = Alignment.Center
                        ) {
                            Icon(
                                imageVector = Icons.Outlined.Check,
                                contentDescription = "Checked",
                                modifier = Modifier
                                    .padding(4.dp)
                                    .size(16.dp),
                                tint = MaterialTheme.colorScheme.surface
                            )
                        }
                    }
                }
            }
        }
    }
}

@Composable
private fun UseSystemColor() {
    val context = LocalContext.current
    val scope = rememberCoroutineScope()
    val systemColor = LocalSystemPrimaryModel.current
    Surface(
        modifier = Modifier.fillMaxSize(),
        color = MaterialTheme.colorScheme.primary.copy(alpha = 0.1f),
        shape = CircleShape,
    ) {
        Row(
            modifier = Modifier
                .fillMaxSize()
                .padding(start = 12.dp, end = 8.dp)
        ) {
            Text(
                modifier = Modifier
                    .weight(1f)
                    .align(alignment = Alignment.CenterVertically), text = "跟随系统主题"
            )
            Checkbox(checked = systemColor, onCheckedChange = {
                SystemPrimaryColorPreference.put(
                    context = context,
                    scope = scope,
                    value = systemColor.not()
                )
            })
        }
    }
}

@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun DarkModeSheet(onDismissRequest: () -> Unit) {
    val bottomSheetState = rememberModalBottomSheetState()
    val darkMode = LocalDarkMode.current
    val context = LocalContext.current
    val scope = rememberCoroutineScope()

    ModalBottomSheet(
        onDismissRequest = onDismissRequest,
        sheetState = bottomSheetState,
    ) {
        Column(
            modifier = Modifier
                .padding(horizontal = 16.dp)
                .padding(bottom = 16.dp)
                .selectableGroup()
        ) {
            DarkModePreference.values.forEach {
                Card(
                    colors = CardDefaults.cardColors(containerColor = Color.Transparent)
                ) {
                    Row(
                        Modifier
                            .fillMaxWidth()
                            .height(56.dp)
                            .selectable(
                                selected = (it == darkMode),
                                onClick = {
                                    DarkModePreference.put(
                                        context = context, scope = scope,
                                        value = it
                                    )
                                    onDismissRequest()
                                },
                                role = Role.RadioButton
                            )
                            .padding(horizontal = 16.dp),
                        verticalAlignment = Alignment.CenterVertically
                    ) {
                        RadioButton(
                            selected = (it == darkMode),
                            onClick = null
                        )
                        Text(
                            text = DarkModePreference.toDisplayName(it),
                            style = MaterialTheme.typography.bodyLarge,
                            modifier = Modifier.padding(start = 16.dp)
                        )
                    }
                }
            }
        }
    }
}

@Composable
private fun CustomColorDialog(
    visible: Boolean,
    value: String? = null,
    onDismissRequest: () -> Unit = {},
    onConfirm: (String?) -> Unit = {},
) {
    var myValue by rememberSaveable { mutableStateOf(value) }
    if (visible) {
        AlertDialog(
            onDismissRequest = {},
            title = {
                Text(text = "选择颜色")
            },
            text = {
                ColorSlider(value) {
                    myValue = it
                }
            },
            confirmButton = {
                TextButton(onClick = { onConfirm(myValue) }) {
                    Text(text = stringResource(id = R.string.sure))
                }
            },
            dismissButton = {
                TextButton(onClick = onDismissRequest) {
                    Text(text = stringResource(id = R.string.cancel))
                }
            },
        )
    }
}


@Composable
private fun ColorSlider(value: String?, backValue: (String) -> Unit) {
    val localColor = value?.toColorOrNull() ?: Color.Transparent
    var rSliderPosition by remember { mutableFloatStateOf(localColor.red) }
    var gSliderPosition by remember { mutableFloatStateOf(localColor.green) }
    var bSliderPosition by remember { mutableFloatStateOf(localColor.blue) }
    val color = calculateColor(rSliderPosition, gSliderPosition, bSliderPosition)
    val txtValue = color.toSrgb().toHex()
    backValue(txtValue)
    Column(
        modifier = Modifier
            .fillMaxWidth(),
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        Slider(
            value = rSliderPosition,
            colors = SliderDefaults.colors(thumbColor = Color(rSliderPosition, 0f, 0f, 1f)),
            onValueChange = { newPosition ->
                rSliderPosition = newPosition
            }
        )
        Slider(
            value = gSliderPosition,
            colors = SliderDefaults.colors(thumbColor = Color(0f, gSliderPosition, 0f, 1f)),
            onValueChange = { newPosition ->
                gSliderPosition = newPosition
            }
        )
        Slider(
            value = bSliderPosition,
            colors = SliderDefaults.colors(thumbColor = Color(0f, 0f, bSliderPosition, 1f)),
            onValueChange = { newPosition ->
                bSliderPosition = newPosition
            }
        )
        Text(
            modifier = Modifier
                .fillMaxWidth()
                .padding(top = 10.dp)
                .height(50.dp)
                .background(color)
                .padding(top = 12.dp),
            text = txtValue,
            color = Color.White,
            textAlign = TextAlign.Center,
        )
    }
}

private fun calculateColor(red: Float, green: Float, blue: Float): Color {
    return Color(red, green, blue, 1f)
}


